// ++++++++++++++++++++++++++++++++++++++++
// 《零基础Go语言算法实战》源码
// ++++++++++++++++++++++++++++++++++++++++
// Author:廖显东（ShirDon）
// Blog:https://www.shirdon.com/
// Gitee:https://gitee.com/shirdonl/goAlgorithms.git
// Buy link :https://item.jd.com/14101229.html
// ++++++++++++++++++++++++++++++++++++++++

package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func boyerMooreSearch(text, pattern string) int {
	n := len(text)
	m := len(pattern)

	if m == 0 {
		return 0
	}

	if n < m {
		return -1
	}

	last := make([]int, 256)
	for i := 0; i < 256; i++ {
		last[i] = -1
	}

	for i := 0; i < m; i++ {
		last[pattern[i]] = i
	}

	i := m - 1
	j := m - 1

	for i < n {
		if text[i] == pattern[j] {
			if j == 0 {
				return i
			}
			i--
			j--
		} else {
			k := last[text[i]]
			i += m - min(j, 1+k)
			j = m - 1
		}
	}

	return -1
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func scanFile(filepath string, signatures []string) error {
	// 打开文件
	file, err := os.Open(filepath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 读取文件内容
	contents, err := ioutil.ReadAll(file)
	if err != nil {
		return err
	}

	// 将文件内容转换为字符串
	text := string(contents)

	// 搜索文件中的每个签名
	for _, signature := range signatures {
		index := boyerMooreSearch(text, signature)
		if index != -1 {
			// 找到签名
			fmt.Printf("文件 %s 在索引处包含恶意软件签名 %s %d\n", filepath, signature, index)
		}
	}

	return nil
}

func main() {
	// 恶意软件特征库
	signatures := []string{"恶意软件签名 1", "恶意软件签名 2", "恶意软件签名 3"}

	// 扫描目录中的所有文件
	dir := "./"
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		panic(err)
	}
	for _, file := range files {
		if !file.IsDir() {
			filepath := fmt.Sprintf("%s/%s", dir, file.Name())
			err := scanFile(filepath, signatures)
			if err != nil {
				fmt.Printf("扫描文件时出错 %s: %s\n", filepath, err)
			}
		}
	}
}

//$ go run interview10-12.go
//文件 .//interview10-12.go 在索引处包含恶意软件签名 恶意软件签名 1 1260
//文件 .//interview10-12.go 在索引处包含恶意软件签名 恶意软件签名 2 1284
//文件 .//interview10-12.go 在索引处包含恶意软件签名 恶意软件签名 3 1308
